package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
)

func main() {
	var start, end int
	fmt.Println("请输入爬取起始页（>=1）：")
	fmt.Scan(&start)
	fmt.Println("请输入爬取终止页(>=start);")
	fmt.Scan(&end)
	toWork(start, end)
}

func toWork(start, end int) {
	fmt.Printf("正在爬取第%d页到第%d页的数据\n", start, end)

	page := make(chan int)

	for i := start; i <= end; i++ {
		go Spider(i, page)
	}
	for i := start; i <= end; i++ {
		fmt.Printf("——第%d页爬取完成——\n", <-page)
	}

}

func Spider(idx int, page chan int) {
	//拼接url https://www.pengfue.com/index_4.html
	url := "https://www.pengfue.com/index_" + strconv.Itoa(idx) + ".html"

	//封装函数段子的url
	result, err := get(url)
	if err != nil {
		fmt.Println("get err", err)
	}
	//解析、编译结果
	ret := regexp.MustCompile(`<h1 class="dp-b"><a href="(?s:(.*?))"`)

	//根据需要信息——每个段子的url
	alls := ret.FindAllStringSubmatch(result, -1)

	//创建用户存储title、content的切片
	fileTile := make([]string, 0)
	fileContent := make([]string, 0)

	for _, url := range alls {
		//fmt.Println("url",url[1])
		title, content, err := SpoderJokepage(url[1]) //爬取一个笑话页面的title和content
		if err != nil {
			fmt.Println("SpoderJokepage err", err)
			continue
		}
		//fmt.Println("title",title)
		//fmt.Println("content",content)

		fileTile = append(fileTile, title)         //将title追加到切片末尾
		fileContent = append(fileContent, content) //将fileContent追加到切片末尾
	}
	saveToFile(fileTile, fileContent, idx)
	page <- idx
}

func saveToFile(fileTile, fileContent []string, idx int) {
	file, err := os.Create("第" + strconv.Itoa(idx) + "页.txt")
	if err != nil {
		fmt.Println("creat err", err)
		return
	}
	defer file.Close()
	n := len(fileTile)
	for i := 0; i < n; i++ {
		file.WriteString(fileTile[i] + "\n" + fileContent[i] + "\n")
		file.WriteString("——————————————————————\n")
	}
}

//爬取一个页面的title和content
func SpoderJokepage(url string) (title, content string, err error) {
	result, err1 := get(url)
	if err1 != nil {
		err = err1
		return
	}
	//编译解析正则表达式——获取title
	ret := regexp.MustCompile(`<h1>(?s:(.*?))</h1>`)

	alls := ret.FindAllStringSubmatch(result, 1) //有两处，取第一个

	//提取title
	for _, tmpTitle := range alls {
		title = tmpTitle[1]
		break
	}
	//编译解析正则表达式——获取content
	ret2 := regexp.MustCompile(`<div class="content-txt pt10">(?s:(.*?))<a`)

	alls2 := ret2.FindAllStringSubmatch(result, 1) //有两处，取第一个

	//提取content
	for _, tmpContent := range alls2 {
		content = tmpContent[1]
		//content = strings.Replace(content, " ", "", -1)
		content = strings.Replace(content, "\n", "", -1)
		content = strings.Replace(content, "\t", "", -1)
		break
	}
	return
}

//获取一个网页的所有内容
func get(url string) (result string, err error) {
	resp, err1 := http.Get(url)
	if err1 != nil {
		err = err1
		return
	}
	defer resp.Body.Close()
	buf := make([]byte, 4096)

	for {
		n, err2 := resp.Body.Read(buf)
		if n == 0 {
			break
		}
		if err2 != nil && err2 != io.EOF {
			err = err2
			return
		}
		result += string(buf[:n])
	}
	return
}
